/*
*  gmain.c - Vobri 'main' window
*  Copyright (c) 2005 Derek Ingrouville (dergro@users.sourceforge.net)
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <string.h>

#include "gmain.h"
#include "gdialog.h"
#include "eventproc.h"

/* Draw window */
static void draw_main_window (GMainWindow *gmain);
static void draw_menus (GMainWindow *gmain);
static void draw_login_area (GMainWindow *gmain);
static void draw_active_area (GMainWindow *gmain);

/* Callbacks */
static gboolean login_clicked (GtkWidget *widget, GdkEventButton *event, gpointer data);
static gboolean window_closed (GtkWidget *widget, GdkEvent *event, gpointer data);

/* Menu Handlers */
static void menu_file_signout_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_file_quit_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_account_disp_name_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_account_status_menu_clicked (GtkRadioAction *action, 
				 	  GtkRadioAction *radioaction, 
					 GMainWindow *gmain);
static void menu_contacts_send_msg_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_contacts_add_contact_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_contacts_add_group_clicked (GtkAction *action, GMainWindow *gmain);
static void menu_contacts_show_offline_clicked (GtkToggleAction *action, GMainWindow *gmain);
static void menu_contacts_show_empty_clicked (GtkToggleAction *action, GMainWindow *gmain);
static void menu_help_about_clicked (GtkAction *action, GMainWindow *gmain);

gboolean gmain_login (GMainWindow *gmain);


/* ----- Menu Items ----- */
/* Normal items */
static const GtkActionEntry menu_entries[] = {
	{ "FileMenu", NULL, "_File" },
	{ "FileSignOut", NULL, "Sign _Out", NULL, NULL, G_CALLBACK (menu_file_signout_clicked) },
	{ "FileQuit", NULL, "_Quit", "<control>Q", NULL, G_CALLBACK (menu_file_quit_clicked) },

	{ "AccountMenu", NULL, "_Account" },
	{ "AccountChangeName", NULL, "Change Display name", NULL, NULL, G_CALLBACK (menu_account_disp_name_clicked) },
	{ "AccountStatusMenu", NULL, "Change Status" },

	{ "ContactsMenu", NULL, "_Contacts" },
	{ "ContactsSendIM", NULL, "Send an Instand Message", NULL, NULL, G_CALLBACK (menu_contacts_send_msg_clicked) },
	{ "ContactsAddContact", NULL, "Add Contact", NULL, NULL, G_CALLBACK (menu_contacts_add_contact_clicked) },
	{ "ContactsAddGroup", NULL, "Add Group", NULL, NULL, G_CALLBACK (menu_contacts_add_group_clicked) },

	{ "HelpMenu", NULL, "_Help" },
	{ "HelpAbout", NULL, "_About", NULL, NULL, G_CALLBACK (menu_help_about_clicked) }
};

/* Radio items */
static const GtkRadioActionEntry menu_radio_entries[] = {
	{ "AccountStatusMenuOnline", NULL, "Online", NULL, NULL, ONLINE },
	{ "AccountStatusMenuAway", NULL, "Away", NULL, NULL, AWAY },
	{ "AccountStatusMenuIdle", NULL, "Idle", NULL, NULL, IDLE },
	{ "AccountStatusMenuBRB", NULL, "Be Right Back", NULL, NULL, BRB },
	{ "AccountStatusMenuBusy", NULL, "Busy", NULL, NULL, BUSY },
	{ "AccountStatusMenuLunch", NULL, "Out to Lunch", NULL, NULL, LUNCH },
	{ "AccountStatusMenuPhone", NULL, "On The Phone", NULL, NULL, PHONE },
	{ "AccountStatusMenuHidden", NULL, "Appear Offline", NULL, NULL, HIDDEN }
};

/* Toggle items */
static const GtkToggleActionEntry menu_toggle_entries[] = {
	{ "ContactsShowOffline", NULL, "Show Offline Contacts", NULL, NULL, G_CALLBACK (menu_contacts_show_offline_clicked) },
	{ "ContactsShowEmpty", NULL, "Show Empty Groups", NULL, NULL, G_CALLBACK (menu_contacts_show_empty_clicked) }
};

static const char *menu_description =
"<ui>"
"  <menubar name='MainMenu'>"
"    <menu action='FileMenu'>"
"      <menuitem action='FileSignOut'/>"
"      <menuitem action='FileQuit'/>"
"    </menu>"
"    <menu action='AccountMenu'>"
"      <menuitem action='AccountChangeName'/>"
"      <menu action='AccountStatusMenu'>"
"        <menuitem action='AccountStatusMenuOnline'/>"
"        <menuitem action='AccountStatusMenuAway'/>"
"        <menuitem action='AccountStatusMenuIdle'/>"
"        <menuitem action='AccountStatusMenuBRB'/>"
"        <menuitem action='AccountStatusMenuBusy'/>"
"        <menuitem action='AccountStatusMenuLunch'/>"
"        <menuitem action='AccountStatusMenuPhone'/>"
"       <menuitem action='AccountStatusMenuHidden'/>"
"      </menu>"
"    </menu>"
"    <menu action='ContactsMenu'>"
"      <menuitem action='ContactsSendIM'/>"
"      <separator/>"
"      <menuitem action='ContactsAddContact'/>"
"      <menuitem action='ContactsAddGroup'/>"
"      <separator/>"
"      <menuitem action='ContactsShowOffline'/>"
"      <menuitem action='ContactsShowEmpty'/>"
"    </menu>"
"    <menu action='HelpMenu'>"
"      <menuitem action='HelpAbout'/>"
"    </menu>"
"  </menubar>"
"</ui>";

/* ---------- Initialization ---------- */

GMainWindow *
gmain_window_new ()
{
	GMainWindow *gmain = NULL;

	gmain = g_new (GMainWindow, 1);

	gmain->window = NULL;
	gmain->menubar = NULL;
	gmain->ui_manager = NULL;
	gmain->accel_group = NULL;
	gmain->action_area = NULL;
	gmain->action_widget = NULL;
	gmain->login = NULL;
	gmain->active = NULL;
	gmain->state = GMAIN_STATE_INVALID;

	/* Draw all needed widgets */
	draw_main_window (gmain);
	draw_login_area (gmain);
	draw_active_area (gmain);

	return gmain;
}

void
gmain_window_reset (GMainWindow *gmain)
{
	g_return_if_fail (gmain != NULL);

	/* Close any open convos */
	if (gmain->active->convos != NULL) {
		GList *list = NULL;
		list = gmain->active->convos;
		while (list != NULL) {
			GConvo *convo = (GConvo *) list->data;
			if (convo == NULL)
				break;

			gconvo_close (convo);
			list = g_list_next (list);
		}
		g_list_free (gmain->active->convos);
		gmain->active->convos = NULL;
	}

	if (gmain->active->session != NULL) {
		msn_signout (gmain->active->session);
		gmain->active->session = NULL;
	}

	if (gmain->active->gclist != NULL) {
		gclist_reset (gmain->active->gclist);
	}

	gmain_disable_appropriate_menus (gmain);
	gmain_window_login_show (gmain);
}

void
gmain_window_close (GMainWindow *gmain)
{
	/* Close any open convos */
	if (gmain->active->convos != NULL) {
		GList *list = NULL;
		list = gmain->active->convos;
		while (list != NULL) {
			GConvo *convo = (GConvo *) list->data;
			if (convo == NULL)
				break;

			gconvo_close (convo);
			list = g_list_next (list);
		}
		g_list_free (gmain->active->convos);
		gmain->active->convos = NULL;
	}

	if (gmain->active->session != NULL) {
		msn_signout (gmain->active->session);
		gmain->active->session = NULL;
	}

	if (gmain->active->gclist != NULL) {
		gclist_free (gmain->active->gclist);
		gmain->active->gclist = NULL;
	}

	if (gmain->window != NULL) {
		g_object_unref (gmain->login->alignment);
		g_object_unref (gmain->active->vbox);
		gtk_widget_destroy (GTK_WIDGET (gmain->window));
		gmain->window = NULL;
	}

	if (gmain->login != NULL) {
		g_free (gmain->login);
		gmain->login = NULL;
	}

	if (gmain->active != NULL) {
		g_free (gmain->active);
		gmain->active = NULL;
	}

	gmain->window = NULL;
	gmain->menubar = NULL;
	gmain->ui_manager = NULL;
	gmain->accel_group = NULL;
	gmain->action_area = NULL;
	gmain->action_widget = NULL;
	gmain->state = GMAIN_STATE_INVALID;

	return;
}

/* ---------- UI Draw ---------- */

static void 
draw_main_window (GMainWindow *gmain)
{
	GtkWidget *window;
	GtkWidget *vbox;           /* vbox containing all other widgets */
	GtkWidget *center_vbox;    /* Center vbox for widgets */
	GtkWidget *statusbar;      /* Statusbar at bottom of window */

	/* Create window and vbox and pack the vbox */
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size (GTK_WINDOW (window), 350, 550);
	gtk_window_set_title ( GTK_WINDOW (window), "Vobri - Minimal MSN Messenger Client");
	vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (window), vbox);

	/* Setup the menus */
	draw_menus (gmain);
	g_assert (gmain->menubar != NULL);
	gtk_box_pack_start (GTK_BOX (vbox),
		GTK_WIDGET (gmain->menubar),
		FALSE, FALSE, 0);
	if (gmain->accel_group != NULL)
		gtk_window_add_accel_group (GTK_WINDOW (window), gmain->accel_group);

	/* Center vbox  */
	center_vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (vbox), center_vbox);

	/* Statusbar */
	statusbar = gtk_statusbar_new ();
	gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0);

	/* Setup signals */
	gtk_signal_connect (GTK_OBJECT (window),
		"delete_event",
		G_CALLBACK (window_closed),
		gmain);

	gmain->window = (GtkWindow *) window;
	gmain->action_area = center_vbox;
}

static void
draw_menus (GMainWindow *gmain)
{
	GtkWidget *menubar;
	GtkActionGroup *action_group;
	GtkUIManager *ui_manager;
	GtkAccelGroup *accel_group;
	GError *error = NULL;

	action_group = gtk_action_group_new ("MenuActions");
	gtk_action_group_add_actions (action_group, menu_entries, G_N_ELEMENTS (menu_entries), gmain);
	gtk_action_group_add_toggle_actions (action_group, menu_toggle_entries, G_N_ELEMENTS (menu_toggle_entries), gmain);
	gtk_action_group_add_radio_actions (action_group, menu_radio_entries,
		G_N_ELEMENTS (menu_radio_entries),
		ONLINE,
		G_CALLBACK (menu_account_status_menu_clicked),
		gmain);

	ui_manager = gtk_ui_manager_new ();
	gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);

	accel_group = gtk_ui_manager_get_accel_group (ui_manager);

	if (!gtk_ui_manager_add_ui_from_string (ui_manager, menu_description, -1, &error))
	{
		g_error ("Building menus failed: %s\n", error->message);
		g_error_free (error);
		return;
	}

	menubar = gtk_ui_manager_get_widget (ui_manager, "/MainMenu");

	gmain->menubar = GTK_MENU_BAR (menubar);
	gmain->accel_group = accel_group;
	gmain->ui_manager = ui_manager;

	/* Set menus to an appropriate state */
	gmain_disable_appropriate_menus (gmain);

	return;
}

static void
draw_login_area (GMainWindow *gmain)
{
	GMainWindowLogin *login = NULL;
	GtkWidget *label;
	GtkWidget *alignment;
	GtkWidget *eventbox;

	/* Label Formatting */
	PangoAttrList *list;
	PangoAttribute *attr;
	PangoColor color;

	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->window != NULL);

	/* new Login structure */
	login = g_new (GMainWindowLogin, 1);

	/* setup alignment widget */
	alignment = gtk_alignment_new (0.5, 0.15, 0.0, 0.0);

	/* Create the eventbox */
	eventbox = gtk_event_box_new ();
	gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);

	/* Create label */
	label = gtk_label_new (NULL);
	list = pango_attr_list_new ();

	/* Create attributes */
	/* Bold */
	attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
	attr->start_index = 0;
	attr->end_index = G_MAXINT;
	pango_attr_list_insert (list, attr);

	/* Foreground */
	pango_color_parse (&color, "#4d7aad");
	attr = pango_attr_foreground_new (color.red, color.green, color.blue);
	attr->start_index = 0;
	attr->end_index = G_MAXINT;
	pango_attr_list_insert (list, attr);

	/* Underline */
	attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
	attr->start_index = 0;
	attr->end_index = G_MAXINT;
	pango_attr_list_insert (list, attr);

	gtk_label_set_attributes (GTK_LABEL (label), list);
	pango_attr_list_unref (list);

	/* Pack the widgets */
	gtk_container_add (GTK_CONTAINER (alignment), eventbox);
	gtk_container_add (GTK_CONTAINER (eventbox), (GtkWidget *) label);

	g_signal_connect (G_OBJECT (eventbox),
		"button_press_event",
		G_CALLBACK (login_clicked),
		gmain);

	login->alignment = GTK_ALIGNMENT (alignment);
	login->eventbox = eventbox;
	login->label = GTK_LABEL (label);
	gmain->login = login;
}

static void
draw_active_area (GMainWindow *gmain)
{
	GMainWindowActive *active = NULL;
	GCList *clist = NULL;
	GtkWidget *vbox;
	GtkWidget *label;
	GtkWidget *align;
	GtkWidget *hsep;	

	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->window != NULL);

	/* Needed structures */
	active = g_new (GMainWindowActive, 1);
	clist = gclist_new (gmain);

	/* This vbox will hold all widgets created here */
	vbox = gtk_vbox_new (FALSE, 0);

	/* Label that will show contacts displayname and status */
	label = gtk_label_new (NULL);
	align = gtk_alignment_new (0, 0, 0, 0);
	gtk_alignment_set_padding (GTK_ALIGNMENT (align), 5, 5, 5, 10);
	gtk_container_add (GTK_CONTAINER (align), label);

	/* Separates label from contact list */
	hsep = gtk_hseparator_new ();

	/* Add everything to the vbox */
	gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), hsep, FALSE, FALSE, 0);
	
	/* Add the contact list to our vbox*/
	gtk_box_pack_start (GTK_BOX (vbox),
		GTK_WIDGET (clist->scrolled_window),
		TRUE, TRUE, 0);

	active->vbox = GTK_VBOX (vbox);
	active->dispname = GTK_LABEL (label);
	active->gclist = clist;
	active->convos = NULL;
	active->session = NULL;
	gmain->active = active;
}

int
gmain_window_login_show (GMainWindow *gmain)
{
	char *text = "Sign In";

	g_return_val_if_fail (gmain != NULL, -1);
	g_return_val_if_fail (gmain->window != NULL, -1);
	g_return_val_if_fail (gmain->login != NULL, -1);

	/* Label */
	gtk_label_set_text (gmain->login->label, text);

	if (gmain->state == GMAIN_STATE_ACTIVE && gmain->action_widget != NULL ) 
	{
		gtk_container_remove (GTK_CONTAINER (gmain->action_area), 
				      gmain->action_widget);	
	}

	
	/* So we can use this after it is removed */
	g_object_ref (gmain->login->alignment);

	gtk_container_add (GTK_CONTAINER (gmain->action_area),
			   GTK_WIDGET (gmain->login->alignment));


	/* Show Hand on "Sign In" label mouseover */
	gtk_widget_realize (GTK_WIDGET (gmain->login->eventbox));
	gdk_window_set_cursor (gmain->login->eventbox->window, 
				gdk_cursor_new (GDK_HAND1));

	gtk_window_resize (gmain->window, 350, 550);

	gtk_widget_show_all (GTK_WIDGET (gmain->window));

	gmain->action_widget = GTK_WIDGET (gmain->login->alignment);
	gmain->state = GMAIN_STATE_LOGIN;

	return 0;
}


int
gmain_window_clist_show (GMainWindow *gmain)
{
	
	g_return_val_if_fail (gmain != NULL, -1);
	g_return_val_if_fail (gmain->window != NULL, -1);
	g_return_val_if_fail (gmain->active != NULL, -1);

	/* Make sure things are happening in the proper order */
	g_assert (gmain->state == GMAIN_STATE_LOGIN);

	/* Remove login widget from action_area */
	if (gmain->action_widget != NULL) 
	{
		gtk_container_remove (GTK_CONTAINER (gmain->action_area), 
				      gmain->action_widget);	
	}

	/* So we can use this after it is removed */
	g_object_ref (gmain->active->vbox);

	/* Add our vbox */
	gtk_container_add (GTK_CONTAINER (gmain->action_area), 
			GTK_WIDGET (gmain->active->vbox));

	gtk_window_resize (gmain->window, 350, 550);

	gtk_widget_show_all (GTK_WIDGET (gmain->window));

	gmain->action_widget = GTK_WIDGET (gmain->active->vbox);
	gmain->state = GMAIN_STATE_ACTIVE;

	return 0;
}

void gmain_activate_appropriate_menus (GMainWindow *gmain)
{
	GtkWidget *widget = NULL;
	GtkUIManager *ui = NULL;

	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->ui_manager != NULL);

	ui = gmain->ui_manager;

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/FileMenu/FileSignOut");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/AccountMenu/AccountChangeName");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/AccountMenu/AccountStatusMenu");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsSendIM");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsAddContact");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsAddGroup");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsShowOffline");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsShowEmpty");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, TRUE);

	return;
}

void
gmain_disable_appropriate_menus (GMainWindow *gmain)
{
	GtkWidget *widget = NULL;
	GtkUIManager *ui = NULL;

	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->ui_manager != NULL);

	ui = gmain->ui_manager;

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/FileMenu/FileSignOut");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/AccountMenu/AccountChangeName");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/AccountMenu/AccountStatusMenu");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsSendIM");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsAddContact");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsAddGroup");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsShowOffline");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	widget = gtk_ui_manager_get_widget (ui, "/MainMenu/ContactsMenu/ContactsShowEmpty");
	if (widget != NULL)
		gtk_widget_set_sensitive (widget, FALSE);

	return;
}

/* ---------- Session Management ---------- */

gboolean
gmain_login (GMainWindow *gmain)
{
	GLoginDialog *glogin = NULL;
	const char *passport = NULL;
	const char *password = NULL;
	char *status = "Signing In";
	int result = 0;

	glogin = glogin_dialog_new ();
	result = glogin_dialog_show (glogin);

	if (result != GTK_RESPONSE_OK) {
		glogin_dialog_free (glogin);
		return FALSE;
	}

	/* Get data to use */
	passport = gtk_entry_get_text (glogin->acct_entry);
	g_print ("passport = %s\n", passport);
	password = gtk_entry_get_text (glogin->pass_entry);
	g_print ("password = %s\n", password);

	/* Init session data */
	gmain->active->session = msn_session_new ();
	msn_account_set_passport (gmain->active->session->acct, passport);
	msn_account_set_password (gmain->active->session->acct, password);

	/* Free login dialog */
	glogin_dialog_free (glogin);

	gtk_label_set_text (gmain->login->label, status);
	/* Process the changes */
	while (gtk_events_pending ())
		gtk_main_iteration ();

	if (!glogin_signin (gmain->active->session)) {
		msn_session_free (gmain->active->session);
		gmain->active->session = NULL;
		return FALSE;
	}

	/* TODO: Should this be done here? */
	msn_callbacks_set_event_data (gmain->active->session->notif->conn->callbacks, 
		gmain);

	gmain_activate_appropriate_menus (gmain);
	gmain_window_clist_show (gmain);

	return TRUE;
}

void
gmain_window_update_nickname (GMainWindow *gmain)
{
	gchar *str = NULL;
	gchar *status = NULL;

	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->active->dispname != NULL);

	g_assert (gmain->active->session != NULL);
	g_return_if_fail (gmain->active->session->acct->nickname != NULL);

	status = get_string_from_status (gmain->active->session->acct->status);
	g_return_if_fail (status != NULL);

	str = g_strdup_printf ("%s (%s)", gmain->active->session->acct->nickname, status);
	gtk_label_set_text (gmain->active->dispname, str);

	g_free (status);
	g_free (str);
}

void
gmain_window_update_status (GMainWindow *gmain)
{
	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->active->session != NULL);

	/* TODO: gtk_radio_action_set_current_value is only available in Gtk 2.10 */	
	/* TODO: this should fix problem with the inital status and the status menu not being synced */
}

void
gmain_window_update_user (GMainWindow *gmain)
{
	g_return_if_fail (gmain != NULL);
	g_return_if_fail (gmain->active->dispname != NULL);
	g_return_if_fail (gmain->active->session != NULL);

	gmain_window_update_nickname (gmain);
	gmain_window_update_status (gmain);
}

GConvo *
gmain_window_find_convo_from_sboard (GMainWindow *gmain, MsnSwitchboard *sboard)
{
	GConvo *convo = NULL;
	GList *list = NULL;

	g_return_val_if_fail (gmain != NULL, NULL);
	g_return_val_if_fail (sboard != NULL, NULL);

	list = g_list_first (gmain->active->convos);

	while (list != NULL) {
		GConvo *tmp = (GConvo *) list->data;

		if (tmp == NULL)
			break;

		if (tmp->sboard == sboard) {
			convo = tmp;
			break;
		}

		list = g_list_next (list);
	}

	return convo;
}

GConvo *
gmain_window_find_convo_with_participant (GMainWindow *gmain, char *passport)
{
	GConvo *convo = NULL;
	GList *list = NULL;

	g_return_val_if_fail (gmain != NULL, NULL);
	g_return_val_if_fail (passport != NULL, NULL);

	list = g_list_first (gmain->active->convos);

	while (list != NULL) {
		GConvo *tmp = (GConvo *) list->data;
		list = g_list_next (list);

		if (tmp == NULL)
			break;

		if (tmp->primary_contact == NULL)
			continue;

		if (strcmp (tmp->primary_contact->passport, passport) == 0) {
			convo = tmp;
			break;
		}
	}

	return convo;
}

void
gmain_window_add_convo (GMainWindow *gmain, GConvo *convo)
{
	g_return_if_fail (gmain != NULL);
	g_return_if_fail (convo != NULL);

	gmain->active->convos = g_list_append (gmain->active->convos, convo);
	g_print ("gmain: convo added: total convos = %i\n", g_list_length (gmain->active->convos));
}

void
gmain_window_remove_convo (GMainWindow *gmain, GConvo *convo)
{
	g_return_if_fail (gmain != NULL);
	g_return_if_fail (convo != NULL);

	gmain->active->convos = g_list_remove (gmain->active->convos, convo);
	g_print ("gmain: convo removed: total convos = %i\n", g_list_length (gmain->active->convos));
}

int
gmain_window_convo_closed (GConvo *convo, GMainWindow *gmain)
{
	g_return_val_if_fail (convo != NULL, -1);
	g_return_val_if_fail (gmain != NULL, -1);

	gmain_window_remove_convo (gmain, convo);

	return 0;
}

void
gmain_warn_all_convos_hidden_status (GMainWindow *gmain)
{
	GList *list = NULL;

	g_return_if_fail (gmain != NULL);

	list = g_list_first (gmain->active->convos);

	/* Show a warning in each conversation window */
	while (list != NULL) {
		GConvo *tmp = (GConvo *) list->data;
		list = g_list_next (list);

		if (tmp == NULL)
			break;

		gconvo_warn_status_hidden (tmp);
	}

	return;
}

/* ---------- UI Callbacks ---------- */

static gboolean
login_clicked (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	GMainWindow *gmain = (GMainWindow *) data;
	gmain_login (gmain);
	return TRUE;
}

static gboolean
window_closed (GtkWidget *widget, GdkEvent *event, gpointer data)
{
	GMainWindow *gmain = NULL;

	g_return_val_if_fail (data != NULL, FALSE);

	gmain = (GMainWindow *) data;

	gmain_window_close (gmain);

	gtk_main_quit ();

	return FALSE;
}

/* ---------- Menu Callbacks ---------- */

static void
menu_file_signout_clicked (GtkAction *action, GMainWindow *gmain)
{
	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	gmain_window_reset (gmain);
}

static void
menu_file_quit_clicked (GtkAction *action, GMainWindow *gmain)
{
	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	gmain_window_close (gmain);
	/* TODO: check why close doesn't quit */
	gtk_main_quit ();
}

static void
menu_account_disp_name_clicked (GtkAction *action, GMainWindow *gmain)
{
	GNicknameDialog *nick_dialog = NULL;
	gchar *nickname = NULL;
	int ret = 0;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	nick_dialog = nickname_dialog_new (gmain->active->session);
	nickname = nickname_dialog_run (nick_dialog);
	nickname_dialog_free (nick_dialog);

	if (nickname == NULL)
		return;
	else if (strlen (nickname) == 0) {
		g_free (nickname);
		return;
	}

	/* Don't do anything if the nickname hasn't changed */
	if (strcmp (nickname, gmain->active->session->acct->nickname) == 0)
		return;

	/* TODO: Input validation !! */
	ret = msn_change_nickname (gmain->active->session, nickname);

	g_free (nickname);
	g_return_if_fail (ret >= 0);
}

static void
menu_account_status_menu_clicked (GtkRadioAction *action, 
				  GtkRadioAction *radioaction, 
				  GMainWindow *gmain)
{
	MsnSession *session = NULL;
	MsnStatus status;
	int ret = 0;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	status = (MsnStatus) gtk_radio_action_get_current_value (action);
	g_print ("Status menu: value = %i\n", status);

	ret = msn_set_status (gmain->active->session, status);
	if (ret != 0) {
		vobri_display_error (NULL, "Unable to change status");
		g_warning ("Unable to change status, ret = %i\n", ret);
		return;
	}

	/* If we changed status to HIDDEN, warn the user about existing convos */
	if (status == HIDDEN)
		gmain_warn_all_convos_hidden_status (gmain);

	return;
}


static void
menu_contacts_send_msg_clicked (GtkAction *action, GMainWindow *gmain)
{
	GConvo *convo = NULL;
	GSendImDialog *imdialog = NULL;
	MsnStatus status = OFFLINE;
	gchar *passport = NULL;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	status = gmain->active->session->acct->status;

	imdialog = send_im_dialog_new ();
	passport = send_im_dialog_run (imdialog);
	send_im_dialog_free (imdialog);

	if (passport == NULL)
		return;
	else if (strlen (passport) == 0) {
		g_free (passport);
		return;
	}

	/* For now, we only use this with contact on our list */
	if (msn_clist_find_contact (gmain->active->session->clist, passport) == NULL) {
		vobri_display_warning (NULL, 
		  "Feature currently only works with contacts who are on your contact list.");
		g_free (passport);
		return;
	}

	if (status != OFFLINE) {
		convo = gconvo_new (gmain->active->session, SWITCHBOARD_CHAT_NEW);
		gconvo_set_window_closed_cb (convo, gmain_window_convo_closed, gmain);
		gmain_window_add_convo (gmain, convo);
		gconvo_invite_participant (convo, passport);
		gconvo_show (convo);
	}

	g_free (passport);

	return;
}

static void
menu_contacts_add_contact_clicked (GtkAction *action, GMainWindow *gmain)
{
	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);
}

static void
menu_contacts_add_group_clicked (GtkAction *action, GMainWindow *gmain)
{
	GGroupAddDialog *groupdialog = NULL;
	gchar *groupname = NULL;
	int ret = 0;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	groupdialog = group_add_dialog_new ();
	groupname = group_add_dialog_run (groupdialog);
	group_add_dialog_free (groupdialog);

	if (groupname == NULL)
		return;
	else if (strlen (groupname) == 0) {
		g_free (groupname);
		return;
	}

	/* TODO: Input validation !! */

	ret = msn_add_group (gmain->active->session ,groupname);

	g_free (groupname);
	g_return_if_fail (ret >= 0);
}

static void
menu_contacts_show_offline_clicked (GtkToggleAction *action, GMainWindow *gmain)
{
	gboolean state;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	state = gtk_toggle_action_get_active (action);
	gclist_set_show_offline_contacts (gmain->active->gclist, state);
}

static void
menu_contacts_show_empty_clicked (GtkToggleAction *action, GMainWindow *gmain)
{
	gboolean state;

	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);

	state = gtk_toggle_action_get_active (action);
	gclist_set_show_empty_groups (gmain->active->gclist, state);
}

static void
menu_help_about_clicked (GtkAction *action, GMainWindow *gmain)
{
	g_return_if_fail (action != NULL);
	g_return_if_fail (gmain != NULL);
}